// 第三章是数组操作
// 首先需要注意的是new Array(10) 和Array(10)是完全不一样的。
// 前者定义一个长度为10的数组，每个元素都为0；后者定义一个长度为1的数组，值为10
// 前者new了一个对象，后者调用Array.apply()静态方法
// val hello = Array("Hello","scala") // 使用apply方法定义一个长度为2的数组，类型是推断出来的
// hello(1) 使用()来访问数组元素，而不是[]

// 变长数组： import scala.collection.mutable.ArrayBuffer
// val b = new ArrayBuffer[Int]()  // ()可以去掉
// 向变长数组中增加元素，使用+=，
// b+=1  b+=31   注意b是val的，不能再给b赋值：b = new ArrayBuffer[Int]，但是可以向b中添加元素
// 如果添加一个负数，注意+=后面要有个空格，正数不需要空格
// ArrayBuffer后添加多个元素：两种方法b += (1,2,3,4,5)   b ++= ArrayBuffer(1,2,3,4,5)
// 移除前面/后面N个元素：b.trimStart(N) / b.trimEnd(N)

// 在任意位置添加元素： b.insert(3,4) // 是将第3个元素替换成4，后面的其他元素顺移
// 也可以添加任意多个元素 b.insert(3,3,4,4,5,6,7) // 意义同上
// b.insertAll(3, ArrayBuffer(2,2,3)) // 同上，是将新的ArrayBuffer“放在”第3个位置，后面其他元素顺移。
// insertAll不能用 (3, (3,4,5,6))这种形式

// 能添加当然也能删除。
// b.remove(2) 移除第3个元素
// b.remove(2,3) 从第3个位置开始移除3个元素

// 遍历数组
// until其实是RichIn的一个方法, 0 until 10 其实上是 0.until(10)
// 试着输入0 to 10 , 0 until 10
// for(i<- 0 until b.length) println(b(i))  // 比较笨的打印b中所有元素的方法
// for(i<- 0 until b.length reverse) println(b(i))  // 倒序打印
// for(i<- 0 until (b.length,2)) println(b(i))  // 跳位打印
// for (i<- b) println(i) // 如果不需要访问下标，可以像这样简单遍历

// yield
// val b = (1 to 5).toBuffer  // 可以像这样快速创建ArrayBuffer
// val c = for (i<-b) yield i*2  // 将b中每个元素乘以2，生成一个新的ArrayBuffer，赋值给c

// yield 与守卫配合使用
val b = (-4 to 3).toBuffer
val c = for (i<-b if i>0) yield i*3 // 将b中大于0的值乘上3

// 函数式编程，注意和和守卫和yield的区别
b.filter(_ >0).map(_*3)

// 移除数组中除第一个负数之外的所有负数
// 先考虑移除所有负数
for (i<- 0 until b.length if b(i)>=0) yield b(i)
// 再考虑怎么保留第一个负数
var keep = true
for (i<- 0 until b.length if keep || b(i)>=0) yield {
if (b(i) <0) keep = false
b(i)
}


// 常用算法
max
sum
min
length

// sorted返回一个排过序的数组，并不会改变原来的数组
val b = ArrayBuffer(3, -9, 5, 0, -6, -2, 8, -4)
val a = b.sorted
// sortWith需要接收一个函数，最常见的是_<_或 _>_  ， 也可以实现更复杂的逻辑
val c = b.sortWith(_>_)
// scala.util.Sorting.quickSort会改变原来的变量
import scala.util.Sorting.quickSort
quickSort(b) // 这个时候b被修改了
//对于min、max、quickSort这些方法，元素类型必须支持此操作，这包括了数字、字符串以及其他带有Ordered特质的类型

// 如果想显示数组或数组缓冲中的内容，可以用mkString方法，允许指定元素之间的分隔符
// mkString这个方法，要么指定一个参数，即每个元素之间的分隔符，要么指定三个参数，第1个是整体前缀最后一个是整体后缀
b.mkString(",")


// 关于数组，其他有用的方法：
append(e:A*) // 给数组缓冲添加多个元素
appendAll(xs:TraversableOnce[A]) // 添加一个类型为A的集合
count(p:(A)=>Boolean):Int // 接收一个由A到Boolean的函数，返回Int. b.count(_>3):b中包含的大于3的元素的个数
+=(e:A) // b += 33 , b+=(1,2,3,4)
copyToArray[B>:A](xs:Array[B] // 将数组拷贝到另一个数组中，B必须是A的超类，B的长度可以为0，结果自然也是个空数组
max
padTo // 这个似乎很复杂

// 多维数组

// 与Java互操作,使用隐式转换，scala ArrayBuffer到 java List
import scala.collection.JavaConversions._
val a = ArrayBuffer("hello","world","scala")
val processer = new ProcessBuilder(a)
val cmd = processer.command()
cmd

// java List 到 scala Buffer，不能用ArrayBuffer，被包装起来的对象只能保证是一个Buffer，不能保证是ArrayBuffer
import scala.collection.mutable.Buffer
val b:Buffer[String] = processer.command()


import scala.collection.mutable.ArrayBuffer
import scala.util.Random
import java.util.TimeZone
import java.awt.datatransfer._

object charpter03 {
  /*
   * 3.1 
   * 编写一段代码，将a设置为一个n个随机整数的数组，要求随机数介于0和n之间。
   */
   val n = 12
   val a = (for(i<- 1 to n) yield util.Random.nextInt(n)) toArray
   
def q1(n:Int) = {
(for (i<-1 to n)yield Random.nextInt(n)) toArray
}

  def question1(n: Int) = {
    (for (i <- 1 to n) yield Random.nextInt(n)) toArray
  }

  /*
   * 3.2 
   * 编写一个循环，将整数数组中相邻的元素置换。
   */
def q2(arr:Array[Int]) = {
val l = arr.length
for(i<-0 until (if (l%2==0) l else l-1 ,2)) { // 因为这里用到了 0 until (10, 2) （假定l=10），所以i有效的值为0，2，4，6，8， if(l%2==0) l else l-1 没有问题
val tmp = arr(i)
arr(i) = arr(i+1)
arr(i+1)=tmp
}
arr
}

def q2(arr:Array[Int]):Array[Int] = {
val l = arr.length
// 只取序号为单数并且不是最后一个元素的，才执行调换
for (i<-0 to l-1) {
if (i%2==0 && i<l-1) {
val tmp = arr(i)
arr(i)=arr(i+1)
arr(i+1)=tmp
}
}
arr
}


def q2(arr:Array[Int]):Array[Int] = {
val l = arr.length
// 改良写法，to改成until
for (i<-0 until l,2) {
val tmp = arr(i)
arr(i)=arr(i+1)
arr(i+1)=tmp
}
arr
}



  def question2(arr: Array[Int]): Array[Int] = {
    val l = arr.length
    for (i <- 0 until (if (l % 2 == 0) l else l - 1, 2)) {
      val tmp = arr(i)
      arr(i) = arr(i + 1)
      arr(i + 1) = tmp
    }
    arr
  }


  /*
   * 3.3 
   * 重复前一个练习，不过这次生成一个新的值交换过的数组。用for/yield。
   */
// 如果用yield，until后不能用(n,2)这种形式，因为返回的数量和原数量要一致
// if i%2==1，即下标为奇数（元素序号是偶数），直接取左边一个元素
// else if i< l -1 ,下标为偶数（元素序号是奇数）且不是最后一位，取右边一个元素
// else 这一步只剩下i % 2 == 0且i == l-1，即最后一位下标为偶数，所有元素个数为奇数，不执行交换
def q3(arr:Array[Int]) = {
val l = arr.length
for (i<-0 until l) yield {
if (i%2==1) arr(i-1)
else if(i!=l-1) arr(i+1)
else arr(i)
}
}



def q3(arr:Array[Int]) = {
val l = arr.length
for (i<-0 until l) yield {
if (i % 2 == 0) {
if(i<l-1) arr(i+1) else arr(i)
} else arr(i-1)
}
}






  def question3(arr: Array[Int]) = {
    for (i <- 0 until arr.length) yield {
      if (i % 2 == 0) {
        if (i + 1 < arr.length) arr(i + 1) else arr(i)
      }
      else {
        arr(i - 1)
      }
    }
  }

  /*
   * 3.4 
   * 给定一个整数数组，产出一个新的数组，包含元数组中的所有正值，
   * 以原有顺序排列，之后的元素是所有零或负值，以原有顺序排列。
   */
// 这么简单的吗？为什么我想不到。。 用yield根本实现不了啊啊啊
// Array不能用append，ArrayBuffer才有，因为append是在数组后增加元素，是修改了元数组，而Array是immutable的，ArrayBuffer才是mutable的

val arr = Array(-9,3,-5,6,-2,0,-6,4)
def q4(arr:Array[Int]) = {
arr.filter(_>0) ++ arr.filter(_<=0)
}
q4(arr)
// 也可以：（明显上面的要简单……）
val arr = Array(-9,3,-5,6,-2,0,-6,4)
val a1 = arr.filter(_>0)
val a2 = arr.filter(_<=0)
val a3 = a1.toBuffer
a3.appendAll(a2)
a3

  def question4(arr: Array[Int]) = {
    (arr filter { _ > 0 }) ++ (arr filter { _ <= 0 })
  }

  /*
   * 3.5 
   * 如何计算Array[Double]的平均值？
   */
val arr:Array[Double] = Array(-9,3,-5,6,-2,0,-6,4)
arr.sum/arr.length

  def question5(arr: Array[Int]) = {
    arr.sum * 1.0 / arr.length
  }

  /*
   * 3.6 
   * 如何重新组织Array[Int]的元素将它们反序排列？对于ArrayBuffer[Int]你又会怎么做呢？
   */
val arr:Array[Int] = Array(-9,3,-5,6,-2,0,-6,4)
// 使用ArrayBuffer要先导入包：
import scala.collection.mutable.ArrayBuffer
val arr:ArrayBuffer[Int] = ArrayBuffer-9,3,-5,6,-2,0,-6,4)
// 或：
arr.toBuffer.reverse
arr.reverse



  def question6(arr: Array[Int]) = {
    arr reverse
  }

  /*
   * 3.7 
   * 编写一段代码，产出数组中的所有值，去掉重复项。
   */
val arr:Array[Int] = Array(-9,3,-5,6,-2,3,6,-6,0,-6,4)
arr.distinct

  def question7(arr: Array[Int]) = {
    arr distinct
  }

  /*
   * 3.8 
   * 重新编写3.4节结尾的示例。收集负值元素的下标，反序，去掉最后一个下标，
   * 然后对每一个下标调用a.remove(i)。比较这样做的效率和3.4节中另外两种方法的效率。
   */
  def question8(arr: ArrayBuffer[Int]) = {
    var indexes = ArrayBuffer[Int]()
    for (i <- 0 until arr.length if (arr(i) < 0)) indexes.insert(0, i)
    indexes.init foreach { arr remove _ }
    arr
  }	

  /*
   * 3.9 
   * 创建一个由java.util.TimeZone.getAvailableIDs返回的时区集合，判断条件是它们在美洲，去掉”America/“前缀并排序。
   */
val timeZone = java.util.TimeZone.getAvailableIDs
timeZone.filter(_.startWith("America")).map(_.drop(8)).sorted



  def question9 = {
    TimeZone.getAvailableIDs filter { _ startsWith "America" } map { _ drop (8) } sortBy { x => x }
  }

  /*
   * 3.10 
   * 引入java.awt.datatransfer._并构建一个类型为SystemFlavorMap类型的对象，
   * 然后以DataFlavor.imageFlavor为参数调用getNativesForFlavor方法，以Scala缓冲保存返回值。
   */

import java.awt.datatransfer._
val x = SystemFlavorMap.getDefaultFlavorMap().asInstanceOf[SystemFlavorMap]
val flavors = x.getNativesForFlavor(DataFlavor.imageFlavor)
val b:ArrayBuffer[String] = ArrayBuffer()
for (i<- 0 until flavors.size()) {b.append(flavors.get(i))}
b


  def question10 = {
    val smap = SystemFlavorMap.getDefaultFlavorMap().asInstanceOf[SystemFlavorMap]
    val flavors = smap.getNativesForFlavor(DataFlavor.imageFlavor)
    for (i <- 0 until flavors.size()) yield flavors.get(i)
  }

  def main(args: Array[String]): Unit = {
    question4(Array(1, 0, 2, 3)) foreach { println(_) }
  }
}